package com.agileai.bpm.controller.define;

import java.util.ArrayList;
import java.util.List;

import org.codehaus.jettison.json.JSONObject;

import com.agileai.bpm.bizmoduler.define.WfActivityManage;
import com.agileai.bpm.common.ProcessDefineUtil;
import com.agileai.bpm.controller.ui.VariableBox;
import com.agileai.bpm.domain.define.Activity;
import com.agileai.bpm.domain.define.Activity.ActTypes;
import com.agileai.bpm.interceptor.BaseInterceptor;
import com.agileai.bpm.model.ActivitiesDocument.Activities;
import com.agileai.bpm.model.AuditActivityType;
import com.agileai.bpm.model.ControlType;
import com.agileai.bpm.model.EndActivityType;
import com.agileai.bpm.model.ForkActivityType;
import com.agileai.bpm.model.InInterceptorsDocument.InInterceptors;
import com.agileai.bpm.model.InterceptorModelDocument.InterceptorModel;
import com.agileai.bpm.model.InvokeActivityType;
import com.agileai.bpm.model.JoinActivityType;
import com.agileai.bpm.model.ManualActivityType;
import com.agileai.bpm.model.OutInterceptorsDocument.OutInterceptors;
import com.agileai.bpm.model.ProcessDefineDocument;
import com.agileai.bpm.model.ProcessDefineDocument.ProcessDefine;
import com.agileai.bpm.model.StartActivityType;
import com.agileai.bpm.model.WatchActivityType;
import com.agileai.bpm.service.define.DefineService;
import com.agileai.domain.DataParam;
import com.agileai.domain.DataRow;
import com.agileai.hotweb.annotation.PageAction;
import com.agileai.hotweb.controller.core.BaseHandler;
import com.agileai.hotweb.domain.FormSelect;
import com.agileai.hotweb.renders.AjaxRenderer;
import com.agileai.hotweb.renders.LocalRenderer;
import com.agileai.hotweb.renders.ViewRenderer;
import com.agileai.util.StringUtil;

public class WfProcessActivityEditHandler extends BaseHandler{
	
	public WfProcessActivityEditHandler(){
		super();
		this.serviceId = "defineService";
	}
	
	public ViewRenderer prepareDisplay(DataParam param){
		if (StringUtil.isNullOrEmpty(param.get("activityId"))
				&& StringUtil.isNullOrEmpty(param.get("processId"))){
			this.resetParam(param);
		}
		String processId = param.get("processId");
		String activityId = param.get("activityId");
		String curObjType = param.get("curObjType");
		setAttribute("WFP_ID", processId);
		setAttribute("WFA_ID", activityId);
		setAttribute("WFA_TYPE", curObjType);
		setAttribute("curObjType", curObjType);
		initActivityAttributes(activityId,curObjType);
		initTransTypeFormSelectAttribute();
		initActivityTypeFormSelectAttribute();
		return new LocalRenderer(getPage());
	}
	
	public ViewRenderer doClearSessionParamAction(DataParam param){
		this.clearParam();
		return new AjaxRenderer("");
	}
	
	public ViewRenderer doShowVariableBoxAction(DataParam param){
		ProcessDefine processDefine = getProcessDefine();
		VariableBox variableSelectBox = new VariableBox(processDefine,param);
		return variableSelectBox.doShowVariableBoxAction();
	}
	
	public ViewRenderer doChangeVariableTypeAction(DataParam param){
		ProcessDefine processDefine = getProcessDefine();
//		String activityCode = param.get("WFA_CODE");
		VariableBox variableSelectBox = new VariableBox(processDefine,param);
		return variableSelectBox.doChangeVariableTypeAction();
	}
	
	public ViewRenderer doSelectVariableAction(DataParam param){
		ProcessDefine processDefine = getProcessDefine();
//		String activityCode = param.get("WFA_CODE");
		VariableBox variableSelectBox = new VariableBox(processDefine,param);
		return variableSelectBox.doSelectVariableAction();
	}
	
	public ViewRenderer doSaveActivityAction(DataParam param){
		String responseText = FAIL;
		String activityId = param.get("WFA_ID");
		String curObjType = param.get("WFA_TYPE");
		String wfaCode = param.get("WFA_CODE");
		String wfaName = param.get("WFA_NAME");
		String wfaDesc = param.get("WFA_DESC");
		String wfaBizURL = param.get("WFA_BIZ_URL");
		
		WfActivityManage wfActivityManage = this.lookupService(WfActivityManage.class);
		wfActivityManage.updateRecord(activityId, param);

		ProcessDefine processDefine = getProcessDefine();
		Activities activities = processDefine.getActivities();
		if (ActTypes.start.equals(curObjType)){
			StartActivityType startActivityType = activities.getStartActivity();
			startActivityType.setCode(wfaCode);
			startActivityType.setName(wfaName);
			startActivityType.setDescription(wfaDesc);
		}
		else if (ActTypes.end.equals(curObjType)){
			EndActivityType endActivityType = activities.getEndActivity();
			endActivityType.setCode(wfaCode);
			endActivityType.setName(wfaName);
			endActivityType.setDescription(wfaDesc);
		}
		else if (ActTypes.manual.equals(curObjType)){
			ManualActivityType[] manualActivityTypes = activities.getManualActivityArray();
			if (manualActivityTypes != null){
				for (int i=0;i < manualActivityTypes.length;i++){
					ManualActivityType manualActivityType = manualActivityTypes[i];
					if (activityId.equals(manualActivityType.getId())){
						manualActivityType.setCode(wfaCode);
						manualActivityType.setName(wfaName);
						manualActivityType.setDescription(wfaDesc);
						manualActivityType.setBusinessURL(wfaBizURL);
						
						break;
					}
				}
			}
		}
		else if (ActTypes.audit.equals(curObjType)){
			AuditActivityType[] auditActivityTypes = activities.getAuditActivityArray();
			if (auditActivityTypes != null){
				for (int i=0;i < auditActivityTypes.length;i++){
					AuditActivityType auditActivityType = auditActivityTypes[i];
					if (activityId.equals(auditActivityType.getId())){
						auditActivityType.setCode(wfaCode);
						auditActivityType.setName(wfaName);
						auditActivityType.setDescription(wfaDesc);
						auditActivityType.setBusinessURL(wfaBizURL);
						
						break;
					}
				}
			}
		}
		else if (ActTypes.fork.equals(curObjType)){
			ForkActivityType[] forkActivityTypes = activities.getForkActivityArray();
			if (forkActivityTypes != null){
				for (int i=0;i < forkActivityTypes.length;i++){
					ForkActivityType forkActivityType = forkActivityTypes[i];
					if (activityId.equals(forkActivityType.getId())){
						forkActivityType.setCode(wfaCode);
						forkActivityType.setName(wfaName);
						forkActivityType.setDescription(wfaDesc);
						String controlType = param.get("controlType");
						forkActivityType.setControlType(ControlType.Enum.forString(controlType));
						break;
					}
				}
			}
		}	
		else if (ActTypes.join.equals(curObjType)){
			JoinActivityType[] joinActivityTypes = activities.getJoinActivityArray();
			if (joinActivityTypes != null){
				for (int i=0;i < joinActivityTypes.length;i++){
					JoinActivityType joinActivityType = joinActivityTypes[i];
					if (activityId.equals(joinActivityType.getId())){
						joinActivityType.setCode(wfaCode);
						joinActivityType.setName(wfaName);
						joinActivityType.setDescription(wfaDesc);
						String controlType = param.get("controlType");
						joinActivityType.setControlType(ControlType.Enum.forString(controlType));
						
						String matchedForkNode = param.get("matchedForkNode");
						if (!StringUtil.isNullOrEmpty(matchedForkNode)){
							joinActivityType.setMatchedFork(matchedForkNode);							
						}
						break;
					}
				}
			}
		}
		else if (ActTypes.watch.equals(curObjType)){
			WatchActivityType[] watchActivityTypes = activities.getWatchActivityArray();
			if (watchActivityTypes != null){
				for (int i=0;i < watchActivityTypes.length;i++){
					WatchActivityType watchActivityType = watchActivityTypes[i];
					if (activityId.equals(watchActivityType.getId())){
						watchActivityType.setCode(wfaCode);
						watchActivityType.setName(wfaName);
						watchActivityType.setDescription(wfaDesc);
						
						break;
					}
				}
			}
		}
		else if (ActTypes.invoke.equals(curObjType)){
			InvokeActivityType[] invokeActivityTypes = activities.getInvokeActivityArray();
			if (invokeActivityTypes != null){
				for (int i=0;i < invokeActivityTypes.length;i++){
					InvokeActivityType invokeActivityType = invokeActivityTypes[i];
					if (activityId.equals(invokeActivityType.getId())){
						invokeActivityType.setCode(wfaCode);
						invokeActivityType.setName(wfaName);
						invokeActivityType.setDescription(wfaDesc);
						
						break;
					}
				}
			}
		}		
		try {
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("id", activityId);
			jsonObject.put("name", wfaName);
			responseText = jsonObject.toString();
		} catch (Exception e) {
			log.error(e.getLocalizedMessage(), e);
		}
		return new AjaxRenderer(responseText);
	}

	private List<DataRow> buildInterceptors(InterceptorModel[] interceptorModels){
		List<DataRow> result = new ArrayList<DataRow>();
		if (interceptorModels != null){
			for (int i=0; i< interceptorModels.length;i++){
				InterceptorModel interceptorModel = interceptorModels[i];
				DataRow row = new DataRow();
				row.put("interceptorId",interceptorModel.getId());
				row.put("interceptorName",interceptorModel.getName());
				String interceptorType = BaseInterceptor.getInterceptorType(interceptorModel);
				row.put("interceptorType",interceptorType);
				row.put("interceptorTypeName",BaseInterceptor.getInterceptorTypeName(interceptorType));
				result.add(row);
			}
		}
		return result;
	}

	private void initActivityAttributes(String activityId,String curObjType){
		ProcessDefine processDefine = getProcessDefine();
		Activities activities = processDefine.getActivities();
		if (ActTypes.start.equals(curObjType)){
			StartActivityType startActivityType = activities.getStartActivity();
			setAttribute("WFA_CODE", startActivityType.getCode());
			setAttribute("WFA_NAME",startActivityType.getName());
			setAttribute("WFA_DESC", startActivityType.getDescription());
		}
		else if (ActTypes.end.equals(curObjType)){
			EndActivityType endActivityType = activities.getEndActivity();
			setAttribute("WFA_CODE", endActivityType.getCode());
			setAttribute("WFA_NAME",endActivityType.getName());
			setAttribute("WFA_DESC", endActivityType.getDescription());
		}
		else if (ActTypes.manual.equals(curObjType)){
			ManualActivityType[] manualActivityTypes = activities.getManualActivityArray();
			for (int i=0;i < manualActivityTypes.length;i++){
				ManualActivityType manualActivityType = manualActivityTypes[i];
				if (activityId.equals(manualActivityType.getId())){
					setAttribute("WFA_CODE", manualActivityType.getCode());	
					setAttribute("WFA_NAME",manualActivityType.getName());
					setAttribute("WFA_DESC", manualActivityType.getDescription());
					setAttribute("WFA_BIZ_URL", manualActivityType.getBusinessURL());
					
					InInterceptors inInterceptors = manualActivityType.getInInterceptors();
					if (inInterceptors != null){
						InterceptorModel[] inInterceptorModels = inInterceptors.getInterceptorModelArray();
						List<DataRow> inInterceptorModelList = buildInterceptors(inInterceptorModels);
						this.setAttribute("inInterceptorModelList", inInterceptorModelList);
					}
					
					OutInterceptors outInterceptors = manualActivityType.getOutInterceptors();
					if (outInterceptors != null){
						InterceptorModel[] outInterceptorModels = outInterceptors.getInterceptorModelArray();
						List<DataRow> outInterceptorModelList = buildInterceptors(outInterceptorModels);
						this.setAttribute("outInterceptorModelList", outInterceptorModelList);						
					}
					
					break;
				}
			}
		}
		else if (ActTypes.audit.equals(curObjType)){
			AuditActivityType[] auditActivityTypes = activities.getAuditActivityArray();
			for (int i=0;i < auditActivityTypes.length;i++){
				AuditActivityType auditActivityType = auditActivityTypes[i];
				if (activityId.equals(auditActivityType.getId())){
					setAttribute("WFA_CODE", auditActivityType.getCode());	
					setAttribute("WFA_NAME",auditActivityType.getName());
					setAttribute("WFA_DESC", auditActivityType.getDescription());
					setAttribute("WFA_BIZ_URL", auditActivityType.getBusinessURL());
					
					InInterceptors inInterceptors = auditActivityType.getInInterceptors();
					if (inInterceptors != null){
						InterceptorModel[] inInterceptorModels = inInterceptors.getInterceptorModelArray();
						List<DataRow> inInterceptorModelList = buildInterceptors(inInterceptorModels);
						this.setAttribute("inInterceptorModelList", inInterceptorModelList);
					}
					
					OutInterceptors outInterceptors = auditActivityType.getOutInterceptors();
					if (outInterceptors != null){
						InterceptorModel[] outInterceptorModels = outInterceptors.getInterceptorModelArray();
						List<DataRow> outInterceptorModelList = buildInterceptors(outInterceptorModels);
						this.setAttribute("outInterceptorModelList", outInterceptorModelList);						
					}
					
					break;
				}
			}
		}
		else if (ActTypes.fork.equals(curObjType)){
			ForkActivityType[] forkActivityTypes = activities.getForkActivityArray();
			for (int i=0;i < forkActivityTypes.length;i++){
				ForkActivityType forkActivityType = forkActivityTypes[i];
				if (activityId.equals(forkActivityType.getId())){
					setAttribute("WFA_CODE", forkActivityType.getCode());	
					setAttribute("WFA_NAME",forkActivityType.getName());
					setAttribute("WFA_DESC", forkActivityType.getDescription());
					setAttribute("controlType", forkActivityType.getControlType().toString());
					
					break;
				}
			}
		}
		else if (ActTypes.join.equals(curObjType)){
			JoinActivityType[] joinActivityTypes = activities.getJoinActivityArray();
			for (int i=0;i < joinActivityTypes.length;i++){
				JoinActivityType joinActivityType = joinActivityTypes[i];
				if (activityId.equals(joinActivityType.getId())){
					setAttribute("WFA_CODE", joinActivityType.getCode());	
					setAttribute("WFA_NAME",joinActivityType.getName());
					setAttribute("WFA_DESC", joinActivityType.getDescription());
					setAttribute("controlType", joinActivityType.getControlType().toString());
					String machedForkCode = joinActivityType.getMatchedFork();
					FormSelect matchedForkNode = this.buildMachedForkSelect(activities, machedForkCode);
					setAttribute("matchedForkNode",matchedForkNode);
					break;
				}
			}
		}
		else if (ActTypes.watch.equals(curObjType)){
			WatchActivityType[] watchActivityTypes = activities.getWatchActivityArray();
			for (int i=0;i < watchActivityTypes.length;i++){
				WatchActivityType watchActivityType = watchActivityTypes[i];
				if (activityId.equals(watchActivityType.getId())){
					setAttribute("WFA_CODE", watchActivityType.getCode());	
					setAttribute("WFA_NAME",watchActivityType.getName());
					setAttribute("WFA_DESC", watchActivityType.getDescription());
					
					break;
				}
			}
		}
		else if (ActTypes.invoke.equals(curObjType)){
			InvokeActivityType[] invokeActivityTypes = activities.getInvokeActivityArray();
			for (int i=0;i < invokeActivityTypes.length;i++){
				InvokeActivityType invokeActivityType = invokeActivityTypes[i];
				if (activityId.equals(invokeActivityType.getId())){
					setAttribute("WFA_CODE", invokeActivityType.getCode());	
					setAttribute("WFA_NAME",invokeActivityType.getName());
					setAttribute("WFA_DESC", invokeActivityType.getDescription());
					
					InInterceptors inInterceptors = invokeActivityType.getInInterceptors();
					if (inInterceptors != null){
						InterceptorModel[] inInterceptorModels = inInterceptors.getInterceptorModelArray();
						List<DataRow> inInterceptorModelList = buildInterceptors(inInterceptorModels);
						this.setAttribute("inInterceptorModelList", inInterceptorModelList);
					}
					
					break;
				}
			}
		}		
	}
	
	private FormSelect buildMachedForkSelect(Activities activities,String machedForkCode){
		FormSelect matchedForkNode = new FormSelect();
		ForkActivityType[] forkActivityTypes = activities.getForkActivityArray();
		if (forkActivityTypes != null){
			for (int i=0;i < forkActivityTypes.length;i++){
				ForkActivityType forkActivityType = forkActivityTypes[i];
				String forkId = forkActivityType.getCode();
				String forkName = forkActivityType.getName();
				matchedForkNode.addValue(forkId, forkName);
			}	
		}
		matchedForkNode.setSelectedValue(machedForkCode);
		
		return matchedForkNode;
	}
	
	private void resetParam(DataParam param){
		String processId = param.get("WFP_ID");
		String activityId = param.get("WFA_ID");
		String curObjType = param.get("WFA_TYPE");
		param.put("processId",processId);
		param.put("activityId",activityId);
		param.put("curObjType",curObjType);
	}

	public ViewRenderer doChangeTransAttrAction(DataParam param){
		String curTransitionId = param.get("WFT_ID");
		param.put("curTransitionId",curTransitionId);
		resetParam(param);
		return prepareDisplay(param);
	}

	public ViewRenderer doRefreshInterceptorsAction(DataParam param){
		resetParam(param);
		this.setAttribute(param,"focusTabId");
		return prepareDisplay(param);
	}
	
	public ViewRenderer doDeleteInterceptorAction(DataParam param){
		String repsonseText = FAIL;
		ProcessDefine processDefine = getProcessDefine();
		String positionType = param.get("positionType");
		String interceptorId = param.get("interceptorId");
		String activityId = param.get("WFA_ID");
		ProcessDefineUtil.deleteInterceptorModel(processDefine,positionType,activityId,interceptorId);
		repsonseText = SUCCESS;
		return new AjaxRenderer(repsonseText);
	}
	
	@PageAction
	public ViewRenderer moveupInterceptor(DataParam param){
		String repsonseText = FAIL;
		try {
			ProcessDefine processDefine = getProcessDefine();
			String positionType = param.get("positionType");
			String interceptorId = param.get("interceptorId");
			String activityId = param.get("WFA_ID");
			ProcessDefineUtil.moveupInterceptorModel(processDefine,positionType,activityId,interceptorId);
			repsonseText = SUCCESS;
		} catch (Exception e) {
			log.error(e.getLocalizedMessage(), e);
		}
		return new AjaxRenderer(repsonseText);
	}
	
	@PageAction
	public ViewRenderer movedownInterceptor(DataParam param){
		String repsonseText = FAIL;
		try {
			ProcessDefine processDefine = getProcessDefine();
			String positionType = param.get("positionType");
			String interceptorId = param.get("interceptorId");
			String activityId = param.get("WFA_ID");
			ProcessDefineUtil.movedownInterceptorModel(processDefine,positionType,activityId,interceptorId);
			repsonseText = SUCCESS;
		} catch (Exception e) {
			log.error(e.getLocalizedMessage(), e);
		}
		return new AjaxRenderer(repsonseText);
	}
	
	private ProcessDefine getProcessDefine(){
		ProcessDefineDocument processDefineDocument = 
			(ProcessDefineDocument)this.getSessionAttribute(WfProcessDefineEditHandler.ProcessDefineSessionKey);
		return processDefineDocument.getProcessDefine();
	}
	
	protected DefineService getService() {
		return (DefineService)this.lookupService(this.getServiceId());
	}
		
	private void initTransTypeFormSelectAttribute(){
		FormSelect formSelect = new FormSelect();
		formSelect.addValue("XOR", "XOR");
		formSelect.addValue("AND", "AND");
		formSelect.addValue("OR", "OR");
		setAttribute("WFA_TRANS_TYPE", formSelect);
	}
	
	private void initActivityTypeFormSelectAttribute(){
		FormSelect formSelect = new FormSelect();
		formSelect.addValue(Activity.ActTypes.start, "开始节点");
		formSelect.addValue(Activity.ActTypes.end, "结束节点");
		formSelect.addValue(Activity.ActTypes.manual, "人工节点");
		formSelect.addValue(Activity.ActTypes.audit, "审批节点");
		formSelect.addValue(Activity.ActTypes.invoke, "调用节点");
		formSelect.addValue(Activity.ActTypes.watch, "等待节点");
		formSelect.addValue(Activity.ActTypes.fork, "分支节点");
		formSelect.addValue(Activity.ActTypes.join, "合并节点");
		setAttribute("WFA_ACTIVITY_TYPE", formSelect);
	}
}
